#include <iostream>
#include <vector>
#include <cstring>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <pthread.h>
#include <algorithm>
#include <string>

#define BUFFER_SIZE 1024

std::vector<int> clients = std::vector<int>();
pthread_mutex_t clients_mutex = PTHREAD_MUTEX_INITIALIZER;

void broadcast_message(const std::string& message, int sender_fd) 
{
    pthread_mutex_lock(&clients_mutex);
    for (int client_fd : clients) 
    {
        if (client_fd != sender_fd) 
        {
            send(client_fd, message.c_str(), message.size(), 0);
        }
    }
    pthread_mutex_unlock(&clients_mutex);
}

void* handle_client(void* arg) 
{
    int client_fd = *(int*)arg;
    char buffer[BUFFER_SIZE];    
    while (true) 
    {
        ssize_t bytes_received = recv(client_fd, buffer, BUFFER_SIZE, 0);
        if (bytes_received <= 0) 
        {
            close(client_fd);
            pthread_mutex_lock(&clients_mutex);
            clients.erase(std::remove(clients.begin(), clients.end(), client_fd), clients.end());
            std::cerr << "\033[32m" << "客户端" << "\033[33m" << std::to_string(client_fd) << "\033[32m" << "断开连接，当前剩余" << "\033[33m" << clients.size() << "\033[32m" << "个客户端" << "\033[0m" << std::endl;
            pthread_mutex_unlock(&clients_mutex);
            break;
        }
        buffer[bytes_received] = '\0';
        std::string buffer_str = std::string(buffer);
        if (buffer_str == "exit")
        {
            close(client_fd);
            pthread_mutex_lock(&clients_mutex);
            clients.erase(std::remove(clients.begin(), clients.end(), client_fd), clients.end());
            std::cerr << "\033[32m" << "客户端" << "\033[33m" << std::to_string(client_fd) << "\033[32m" << "断开连接，当前剩余" << "\033[33m" << clients.size() << "\033[32m" << "个客户端" << "\033[0m" << std::endl;
            pthread_mutex_unlock(&clients_mutex);
            break;
        }
        std::string message = "客户端" + std::to_string(client_fd) + ": " + buffer_str;
        std::cerr << "\033[33m" << message << "\033[0m" << std::endl;
        broadcast_message(message, client_fd);
    }
    return nullptr;
}

int main(int argc, char* argv[]) 
{
    if (argc == 2 && std::string(argv[1]) == "--help")
    {
        std::cerr << "\033[32m" << "功能：" << "\033[0m" << std::endl;
        std::cerr << "  " << "开启服务端并指定端口号" << std::endl;
        std::cerr << "\033[32m" << "用法：" << "\033[0m" << std::endl;
        std::cerr << "  " << "server [选项|参数]" << std::endl;
        std::cerr << "\033[32m" << "选项：" << "\033[0m" << std::endl;
        std::cerr << "  " << "--help" << std::endl;
        std::cerr << "    " << "输出帮助文档" << std::endl;
        std::cerr << "\033[32m" << "参数：" << "\033[0m" << std::endl;
        std::cerr << "  " << "一个整型数值" << std::endl;
        std::cerr << "    " << "表示端口号" << std::endl;
        return 0;
    }
    if (argc <= 1)
    {
        std::cerr << "\033[31m" << "请输入参数或选项, 可通过\"server --help\"查看帮助文档" << "\033[0m" << std::endl;
        return 1;
    }
    if (argc == 2)
    {
        std::uint16_t port = 0;
        try
        {
            port = std::stoi(argv[1]);
        }
        catch(const std::exception&)
        {
            std::cerr << "\033[31m" << "参数无法转换为无符号16位整数" << "\033[0m" << std::endl;
            return 1;
        }
        int server_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (server_fd < 0) 
        {
            std::cerr << "\033[31m" << "服务端创建套接字失败" << "\033[0m" << std::endl;
            return 1;
        }
        sockaddr_in server_addr;
        server_addr.sin_family = AF_INET;
        server_addr.sin_addr.s_addr = INADDR_ANY;
        server_addr.sin_port = htons(port);
        if (bind(server_fd, (sockaddr*)&server_addr, sizeof(server_addr)) < 0) 
        {
            std::cerr << "\033[31m" << "服务端绑定套接字、IP、端口号失败" << "\033[0m" << std::endl;
            return 1;
        }
        if (listen(server_fd, 10) < 0) 
        {
            std::cerr << "\033[31m" << "服务端监听套接字失败" << "\033[0m" << std::endl;
            return 1;
        }
        std::cerr << "\033[32m" << "服务端开始监听端口号: " << port << "\033[0m" << std::endl;
        int client_fd = 0;
        while (1) 
        {
            sockaddr_in client_addr;
            socklen_t client_addr_len = sizeof(client_addr);
            client_fd = accept(server_fd, (sockaddr*)&client_addr, &client_addr_len);
            if (client_fd < 0) 
            {
                std::cerr << "\033[31m" << "服务端与客户端连接失败，请尝试重连" << "\033[0m" << std::endl;
                continue;
            }
            else
            {
                pthread_mutex_lock(&clients_mutex);
                clients.push_back(client_fd);
                std::cerr << "\033[32m" << "服务端接受客户端连接请求成功, 当前共有" << "\033[33m" << clients.size() << "\033[32m" << "个客户端" << "\033[0m" << std::endl;
                pthread_mutex_unlock(&clients_mutex);
                pthread_t thread;
                pthread_create(&thread, nullptr, handle_client, &client_fd);
                pthread_detach(thread);
            }
        }
        close(server_fd);
    }
    else
    {
        std::cerr << "\033[31m" << "输入参数或选项过多, 可通过\"server --help\"查看帮助文档" << "\033[0m" << std::endl;
        return 1;
    }
    return 0;
}